
package xj.graph2d.app;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import java.util.concurrent.ArrayBlockingQueue;

public class OutputPane
  extends JTabbedPane { 

  public OutputPane() { 
    consolePane = new JTextArea();
    buildPane = new JTextArea();
    errorPane = new JTextArea();
    consolePane.setEditable(false);
    buildPane.setEditable(false);
    errorPane.setEditable(false);
    
    add(new JScrollPane(buildPane), "Build");
    add(new JScrollPane(errorPane), "Problems");
    add(new JScrollPane(consolePane), "Console");

    cout = new PrintStream(new ConsoleOutputStream(), true);
    cerr = new PrintStream(new ConsoleOutputStream(), true);
    cin = new ConsoleInputStream();
    consolePane.addKeyListener(cin);
  }

  protected JTextArea consolePane = null;
  protected JTextArea buildPane = null;
  protected JTextArea errorPane = null;

  protected ConsoleInputStream cin;
  protected PrintStream cout, cerr;

  static PrintStream syserr = System.err;
  static PrintStream sysout = System.out;
  static InputStream sysin = System.in;

  public void clear() { 
    buildPane.setText("");
    errorPane.setText("");
    consolePane.setText("");
  }

  public JTextArea getBuildPane() { 
    return buildPane;
  }

  public JTextArea getErrorPane() { 
    return errorPane;
  }

  public JTextArea getConsolePane() { 
    return consolePane;
  }

  public void showBuildPane() { 
    setSelectedIndex(0);
  }

  public void showErrorPane() { 
    setSelectedIndex(1);
  }

  public void showConsolePane() { 
    setSelectedIndex(2);
    consolePane.requestFocusInWindow();
  }

  public void showErrorMessage(String msg) { 
    errorPane.setText(msg);
    showErrorPane();
  }

  public void clearBuildPane() { 
    buildPane.setText(""); 
  }

  public void updateBuildPane() {
    if (buildPane != null) { 
      javax.swing.text.Document doc = buildPane.getDocument(); 
      if (doc != null) { 
	int len = doc.getLength(); 
	buildPane.setCaretPosition(len);
      }
    }
  }

  public void setInOutStreams() {
    System.setOut(cout);
    System.setErr(cerr);
    System.setIn(cin);
  }

  public void unsetInOutStreams() {
    System.setOut(sysout);
    System.setErr(syserr);
    System.setIn(sysin);
  }

  public void endInput() {
    if (cin != null) { 
      cin.eos();
    }
  }

  class ConsoleOutputStream 
    extends OutputStream { 

    public ConsoleOutputStream() {}

    public void	close() {
      flush();
    }

    public void	flush() {
      consolePane.append(new String(buf, 0, i));
      consolePane.setCaretPosition(consolePane.getDocument().getLength());
      i = 0;
    }

    public void write(int b) {
      buf[i++] = (byte) b;
      if (b == '\n' || i == 1024) { 
	consolePane.append(new String(buf, 0, i));
	consolePane.setCaretPosition(consolePane.getDocument().getLength());
	i = 0;
      }
    }

    byte[] buf = new byte[1024];
    int i = 0;
  }

  // connect to the console, set System.in
  class ConsoleInputStream 
    extends InputStream 
    implements KeyListener { 

    public ConsoleInputStream() {}
    
    public int available() {
      return buf.size();
    }

    public int read() throws IOException { 
      try {
	int b = buf.take(); 
	return b;
      } catch (InterruptedException e) {
	//throw new IOException();
	return - 1;
      }
    }

    ArrayBlockingQueue<Integer> buf = new ArrayBlockingQueue<Integer>(1024);

    protected void pump(char c) { 
      try { 
	buf.put((int) c);
	consolePane.append(new String(new char[] { c }));
	consolePane.setCaretPosition(consolePane.getDocument().getLength());
	if (c == '\n') { 
	  buf.put(-1);
	}

      } catch (InterruptedException e) {}
    }

    protected void eos() {
      try { 
	buf.put(-1);
      } catch (InterruptedException e) {}
    }

    /** Handle the key typed event from the text field. */
    public void keyTyped(KeyEvent e) {
    }

    /** Handle the key-pressed event from the text field. */
    public void keyPressed(KeyEvent e) {
      //displayInfo(e, "KEY PRESSED: ");
      //displayInfo(e, "KEY TYPED: ");
      char c = e.getKeyChar();
      int keyCode = e.getKeyCode();
      int modifiers = e.getModifiersEx();      

      /*
      String keyString, keyString2;
      keyString = "key character = '" + c + "'";
      keyString2 = "key code = " + keyCode + " (" + KeyEvent.getKeyText(keyCode) + ")";
      System.out.println(keyString); 
      System.out.println(keyString2); 
      */
      /*
      int modifiersEx = e.getModifiersEx();
      String modString = "extended modifiers = " + modifiersEx;
      String tmpString = KeyEvent.getModifiersExText(modifiersEx);
      if (tmpString.length() > 0) {
	modString += " (" + tmpString + ")";
      } else {
	modString += " (no extended modifiers)";
      }        
      String actionString = "action key? ";
      if (e.isActionKey()) {
	actionString += "YES";
      } else {
	actionString += "NO";
      }
      System.out.println(modString); 
      System.out.println(actionString); 
      */

      if (e.isActionKey()) { 
	;
      } else { 
	//if (Character.isLetterOrDigit(keyChar)) {
	if (keyCode == KeyEvent.VK_ENTER) {
	  pump('\n');
	} else if (keyCode == KeyEvent.VK_BACK_SPACE) {
	} else if (keyCode == KeyEvent.VK_DELETE) {	  	 	  
	} else if (keyCode == KeyEvent.VK_SHIFT) {	  	 	  
	} else if (keyCode == KeyEvent.VK_CONTROL) {	  	 	  	  
	} else {
	  if ((modifiers & InputEvent.CTRL_DOWN_MASK) == 0) {
	    pump(c);
	  } else { 
	    if (c == 'c') { 
	      eos();
	    }
	  }
	}
      }

    }

    /** Handle the key-released event from the text field. */
    public void keyReleased(KeyEvent e) {
      //displayInfo(e, "KEY RELEASED: ");
    }

  }


}